/*
 * @Author: lmh
 * @Date: 2021-09-12 22:26:20
 * @LastEditTime: 2021-09-13 00:22:38
 * @LastEditors: lmh
 * @Description: 
 */
// 由HTML DOM 生成 VNode 
function getVNode(node) {
    let nodeType = node.nodeType
    let _vnode = null
    if (nodeType == 1) { // 元素
        let nodeName = node.nodeName
        let attrs = node.attributes
        let _attrObj = {}
        for(let i = 0; i < attrs.length; i++) {
            _attrObj[attrs[i].nodeName] = attrs[i].nodeValue 
        }
        _vnode = new VNode(nodeName, _attrObj, undefined, nodeType)

        let childNodes = node.childNodes
        for(let i = 0; i < childNodes.length; i++) {
            _vnode.appendChild(getVNode(childNodes[i]))
        } 
    } else if (nodeType == 3) {
        _vnode = new VNode(undefined, undefined, node.nodeValue, nodeType)
    }

    return _vnode
}

// VNode 到真正的 DOM
function parseVNode(vnode) {
    // 创建 真实的 DOM
    let type = vnode.type
    let _node = null
    if (type === 3) {
        return document.createTextNode(vnode.value) // 创建文本节点
    } else if (type === 1) {
        _node = document.createElement(vnode.tag)

        // 属性
        let data = vnode.data // 现在这个 data 是键值对
        Object.keys(data).forEach(key => {
            let attrName = key
            let attrValue = data[key]
            _node.setAttribute(attrName, attrValue)
        })

        // 子元素
        let children = vnode.children
        children.forEach(subvnode => {
            _node.appendChild(parseVNode(subvnode)) // 递归转换子元素 （虚拟 DOM）
        })

        return _node
    }
}

let rkuohao = /\{\{(.+?)\}\}/g; // 匹配花括号内部的东西
// 根据路径访问对象成员
function getValueByPath(obj, path) {
    let paths = path.split(',')
    let res = obj
    let prop
    while (prop = paths.shift()) {
        res = res[prop]
    }
    return res
}
// 将带有坑的vnode 与数据data结合 得到填充数据的vnode 模拟AST -> vnode行为
function combine(vnode, data) {
    let _type = vnode.type
    let _data = vnode.data
    let _value =  vnode.value
    let _tag = vnode.tag
    let _children = vnode.children

    let _vnode = null

    if (_type === 3) {
        // 对文本处理
        _value = _value.replace(rkuohao, function(_, g) {
            return getValueByPath(data, g.trim())
        })
        _vnode = new VNode(_tag, _data, _value, _type)
    } else if (_type === 1) {
        _vnode = new VNode(_tag, _data, _value, _type);
        _children.forEach(_subvnode => _vnode.appendChild(combine(_subvnode, data)));
    }

    return _vnode
}
